package pers.bc.utils.pub;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; 
import java.util.regex.Pattern;

import pers.bc.utils.Bean.NamingUtil;
import pers.bc.utils.Bean.ReflectionUtil;
import pers.bc.utils.constant.IPubCons;
import pers.bc.utils.constant.IPubEvnCons;
import pers.bc.utils.file.FileUtilbc;

/**
 * 公共常用的
 *
 * @fileRelativePath: PubEnvUtil.java
 * @Date: Created on 2019/3/2 19:41 <br>
 * @author: LiBencheng<br>
 * @version: 1.0<br>
 */
@SuppressWarnings("unchecked")
public final class PubEnvUtil implements Serializable, IPubCons, IPubEvnCons
{
    
    /** @date 2020-11-19 */
    protected static final long serialVersionUID = -7760718169499823413L;
    
    public static String _ENCRYPT_LENGTH = "encrypt_length";
    
    public static String _DEFAULT_LENGTH = "default_length";
    public static String _DECRYPT_LENGTH = "decrypt_length";
    public static String _MULT_LENGTH = "mult_length";
    public static String _OBJECT_SIZE = "object_size";
    
    public static Integer _DEFAULT_VALUE = 16;
    public static Integer _DECRYPT_VALUE = 9;
    public static Integer _MULT_VALUE = 7;
    
    /**
     * *********************************************************** <br>
     * *说明： 检查字符串是否为空或仅由空格字符组成<br>
     * @see <br>
     * @param str
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#isBlank <br>
     * @author LiBencheng <br>
     * @date Created on 2022-5-18 <br>
     * @time 上午7:47:50 <br>
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static boolean isBlank(String str)
    {
        int strLen; //这里跟isEmpty()保持一致了
        if ((str == null) || ((strLen = str.length()) == 0))
            return true;
        for (int i = 0; i < strLen; i++)
        {
            //空白字符也应该被判断成空
            if (!Character.isWhitespace(str.charAt(i)))
                return false;
        }
        
        return true;
    }
    
    /**
     * *********************************************************** <br>
     * *说明：去掉前后空格，判断是否是空字符串 null和"" 都返回 true <br>
     * @see <br>
     * @param str
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#isEmptyWithTrim <br>
     * @author LiBencheng <br>
     * @date Created on 2024-5-16 <br>
     * @time 下午5:22:15 <br>
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static boolean isEmptyWithTrim(final String str) { return str == null || str.trim().length() == 0;}
    
    /**
     * *********************************************************** <br>
     * 说明： 判断是否是空字符串 null和"" 都返回 true
     *
     * @param strs 判断的字符串
     * @return 是否有效
     * @boolean
     * @author licheng
     * @date Created on 2019-8-6
     * @time 上午9:59:42
     * @version 1.0 <br>
     *          ************************************************************ <br>
     */
    public static boolean isEmpty(String... strs)
    {
        if ((strs == null) || (strs.length == 0))
        {
            return true;
        }
        if (strs.length == 1)
        {
            return (strs[0] == null) || (strs[0].length() == 0);
        }
        return false;
    }
    
    public static boolean isEmpty(Long... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(Integer... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(Short... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(char... array)
    {
        return (array == null) || (array.length == 0);
    }
    
    public static boolean isEmpty(Byte... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(Double... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(Float... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isEmpty(Boolean... array)
    {
        if ((array == null) || (array.length == 0))
        {
            return true;
        }
        if (array.length == 1)
        {
            return null == array[0];
        }
        
        return false;
    }
    
    public static boolean isNullObj(Object obj)
    {
        return null == obj;
    }
    
    public static boolean isNotNullObj(Object obj)
    {
        return !isNullObj(obj);
    }
    
    public static boolean isEmptyObj(Object obj)
    {
        {
            Boolean empty = Boolean.TRUE;
            if (isNullObj(obj))
            {
                return empty;
            }
            if (obj instanceof Map)
            {
                empty = ((Map<?, ?>) obj).isEmpty();
            }
            else if (obj instanceof Collection)
            {
                empty = ((Collection<?>) obj).isEmpty();
            }
            else if (obj.getClass().isArray())
            {    
                empty = Arrays.asList(((Object[]) obj)).isEmpty();
            }
            else
            {
                empty = StringUtil.toString(obj).length() < 1;
            }
            return empty;
        }   
    }
    
    public static boolean isNotEmptyObj(Object obj)
    {
        return !isEmptyObj(obj);
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 判断一组字符串是否有效
     *
     * @param obj
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:30:21
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isEffective(Object... obj)
    {
        {
            if (isNullObj(obj))
            {
                return true;
            }
            for (Object o : obj)
            {
                if (!isNullObj(o))
                {
                    return false;
                }
            }
            
            return true;
        }
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 判断集合的有效性
     *
     * @param col
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:30:57
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isEmptyColle(Collection<?> col)
    {
        return (col == null || col.isEmpty());
    }
    
    /**
     * *********************************************************** <br>
     * 说明：判断一组集合是否有效 false代表有值
     *
     * @param cols
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:31:09
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isEffective(Collection<?>... cols)
    {
        if (isNullObj(cols))
        {
            return true;
        }
        for (Collection<?> c : cols)
        {
            if (!isEmptyColle(c))
            {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 判断map是否有效
     *
     * @param map
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:31:19
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isEmptyMap(Map<?, ?> map)
    {
        return (map == null || map.isEmpty());
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 判断一组map是否有效 false代表有值
     *
     * @param maps 需要判断map
     * @return 是否全部有效
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:31:37
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isEffective(Map<?, ?>... maps)
    {
        if (isNullObj(maps))
        {
            return true;
        }
        for (Map<?, ?> m : maps)
        {
            if (!isEmptyMap(m))
            {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * *********************************************************** <br>
     * 说明：对集合大小(长度)进行加密 默认加9 <br>
     *
     * @param target
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getEncryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:10:42 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getEncryptObjSize(Object target)
    {
        return getEncryptObjSize(target, _DECRYPT_VALUE);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：对集合大小(长度)进行加密 <br>
     * 默认加密长度乘为7<br>
     *
     * @param target
     * @param encryptLength
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getEncryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:10:45 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getEncryptObjSize(Object target, int encryptLength)
    {
        return getEncryptObjSize(target, encryptLength, _MULT_VALUE);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：(目标集合对象大小 *加密因子) +加密长度 == 加密实际长度 <br>
     *
     * @param target 目标集合对象
     * @param encryptLength 加密长度
     * @param multLength 加密因子
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getEncryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:50:53 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getEncryptObjSize(Object target, int encryptLength, int multLength)
    {
        return (getObjSize(target) * multLength) + encryptLength + 1;
    }
    
    /**
     * *********************************************************** <br>
     * 说明：对集合下標(长度)进行解密 默认减9 <br>
     *
     * @param index
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getDecryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:36:37 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getDecryptObjSize(int index)
    {
        return getDecryptObjSize(index, _DECRYPT_VALUE);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：对集合下標(长度)进行解密 <br>
     * 获取集合是第零位的值的算法 ((index - decryptLength) / 7) = 1 <br>
     *
     * @param index
     * @param decryptLength
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getDecryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:35:52 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getDecryptObjSize(int index, int decryptLength)
    {
        return getDecryptObjSize(index, decryptLength, _MULT_VALUE);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：获取集合是第零位的值的算法 ((index - decryptLength) / multLength) - 1 = 0<br>
     * ((下标-解密长度 ) / 加密因子)==1 <br>
     *
     * @param index
     * @param decryptLength
     * @param multLength
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getDecryptObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 17:43:35 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getDecryptObjSize(int index, int decryptLength, int multLength)
    {
        if (0 == index)
        {
            return 0;
        }
        int x = ((index - decryptLength) / multLength);
        if (0 == x)
        {
            return 0;
        }
        
        return x - 1;
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 获取当前項目工程工作路径<br>
     *
     * @return <br>
     * @String <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#getWorkPath <br>
     * @author LiBencheng <br>
     * @date Created on 2020-10-13 <br>
     * @time 上午9:57:05 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static String getWorkPath(){ return FileUtilbc.getWorkServerPath();}

    /**
     * *********************************************************** <br>
     * 说明：解密 获取初始大小 解密 获取初始大小 <br>
     *
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getDefaultLength <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 19:29:54 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getDefaultLength() {return getDefaultLength(_DECRYPT_VALUE, _MULT_VALUE);}
    
    /**
     * *********************************************************** <br>
     * 说明：解密 获取初始大小 <br>
     *
     * @param decryptLength 解密长度
     * @param multLength 加密倍数
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getDefaultLength <br>
     * @author LiBencheng <br>
     * @date Created on 2020-12-2 <br>
     * @time 19:06:57 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getDefaultLength(int decryptLength, int multLength)
    {
        int defValue = 0;
        for (;;)
        {
            if (1 == ((defValue - decryptLength) / multLength))
            {
                return defValue;
            }
            defValue++;
        }
        
    }
    
    /**
     * *********************************************************** <br>
     * 说明：获取数组的长度 管他是List还是Java数组还是Map，都能用 <br>
     *
     * @param target
     * @return <br>
     * @int <br>
     * @methods pers.bc.utils.pub.ArrayUtilbc#getObjSize <br>
     * @author LiBencheng <br>
     * @date Created on 2020-11-28 <br>
     * @time 13:46:39 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getObjSize(Object target)
    {
        if (target == null)
        {
            throw new RuntimeException("对象不能为空");
        }
        if (target instanceof Collection)
        {
            return getSize((Collection<?>) target);
        }
        else if (target instanceof Map)
        {
            return getSize((Map<?, ?>) target);
        }
        else if (target.getClass().isArray())
        { 
            return getArraySize(target);
        }
        else if (target instanceof String)
        {
            return ((String) target).length();
        }
        else
        {
            throw new RuntimeException("不能解析" + target.getClass().getName() + "为数组");
        }
    }
    public static int getArraySize(Object target)
    {
        if( target instanceof boolean[])
            return (null == target ? 0 : ((boolean[])target).length);
        if( target instanceof int[])
            return (null == target ? 0 : ((int[])target).length);
        if( target instanceof char[])
            return (null == target ? 0 : ((char[])target).length);
        if( target instanceof short[])
            return (null == target ? 0 : ((short[])target).length);
        if( target instanceof long[])
            return (null == target ? 0 : ((long[])target).length);
        if( target instanceof float[])
            return (null == target ? 0 : ((float[])target).length);
        if( target instanceof double[])
            return (null == target ? 0 : ((double[])target).length);
        if( target instanceof byte[])
            return (null == target ? 0 : ((byte[])target).length);
        
        return getSize((Object[]) target);
    }
    /**
     * *********************************************************** <br>
     * 说明： <br>
     *
     * @param map
     * @return <br>
     * @int <br>
     * @methods nc.pub.itf.tools.pub.CollectionUtil#size <br>
     * @author licheng <br>
     * @date Created on 2019-9-20 <br>
     * @time 下午3:59:05 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getSize(Map<?, ?> map)
    {
        return (null == map ? 0 : map.size());
    }
    
    /**
     * *********************************************************** <br>
     * 说明： <br>
     *
     * @param collection
     * @return <br>
     * @int <br>
     * @methods nc.pub.itf.tools.pub.CollectionUtil#getSize <br>
     * @author licheng <br>
     * @date Created on 2019-9-20 <br>
     * @time 下午4:00:15 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getSize(Collection<?> collection)
    {
        return (null == collection ? 0 : collection.size());
    }
    
    /**
     * *********************************************************** <br>
     * 说明： <br>
     *
     * @param objs
     * @return <br>
     * @int <br>
     * @methods nc.pub.itf.tools.pub.CollectionUtil#getSize <br>
     * @author licheng <br>
     * @date Created on 2019-9-20 <br>
     * @time 下午4:02:12 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int getSize(Object[] objs)
    {
        return (null == objs ? 0 : objs.length);
    }
    
    /**
     * listMap排序
     *
     * @param listMap
     * @param code 排序key
     * @return
     */
    public static List<Map<String, Object>> sortListMap(List<Map<String, Object>> listMap, final String code, final String order)
    {
        {
            if (PubEnvUtil.getSize(listMap) > 0)
            {
                Collections.sort(listMap, new Comparator<Map<String, Object>>()
                {
                    @Override
                    public int compare(Map<String, Object> o1, Map<String, Object> o2)
                    {
                        Integer name1 = Integer.valueOf(StringUtil.toString(o1.get(code)));
                        Integer name2 = Integer.valueOf(StringUtil.toString(o2.get(code)));
                        // 降序
                        if (order != null && order.equals("desc"))
                            return name2.compareTo(name1);
                        else
                            return name1.compareTo(name2);
                    }
                });
            }
        }
        
        return listMap;
    }
    
    /**
     * *********************************************************** <br>
     * 说明：三元表达式,比较操作 <br>
     *
     * @param object
     * @return <br>
     * @Object <br>
     * @methods pers.bc.utils.pub.PubEnvUtilbc#ternaryExpression <br>
     * @author LiBencheng <br>
     * @date Created on 2020-11-21 <br>
     * @time 22:03:23 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static Object ternaryExpression(Object object)
    {
        return isEmptyObj(object) ? null : object;
    }
    
    public static Object nullOfDefValue(Object object, Object defaultValue)
    {
        return ((object != null) ? object : defaultValue);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：从一个对象中获取值 如果对象是Map，则相当于调用get(Object) 如果对象是VO，则相当于执行对应的getter方法 如果name是整数，则相当于获取数组下标对应的对象 <br>
     *
     * @param target
     * @param name
     * @return <br>
     * @Object <br>
     * @methods pers.bc.utils.Bean.ObjectUtil#get <br>
     * @author LiBencheng <br>
     * @date Created on 2020-11-18 <br>
     * @time 下午3:13:14 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static Object getObjValue(Object target, Object name)
    {
        // 如果是Map，用name作为key返回对应的value
        if ((target instanceof Map) && (name instanceof String))
        {
            return ((Map) target).get(name);
        }
        // 如果是List，用name作为索引，返回下标对应的对象
        if ((target instanceof List) && (name instanceof Integer))
        {
            return ((List) target).get((Integer) name);
        }
        if ((target instanceof List) && (name instanceof String))
        {
            throw new RuntimeException("List对象不可用String作为key进行访问");
        }
        // 如果目标对象是数组
        if (target.getClass().isArray() && (name instanceof Integer))
        {
            return Array.get(target, (Integer) name);
        }
        if (target.getClass().isArray() && (name instanceof String))
        {
            throw new RuntimeException("数组不可用String作为key进行访问");
        }
        // 如果是Json格式的键值对表，则将其转换为Map，再获取值
        if ((target instanceof String) && (target.toString().startsWith("{")) && (target.toString().endsWith("}")))
        {
            return getObjValue(JsonUtil.toMap(StringUtil.toString(target)), name);
        }
        // 如果是Json格式的数组，则将其转换为List，再获取值
        if ((target instanceof String) && (target.toString().startsWith("[")) && (target.toString().endsWith("]")))
        {
            return getObjValue(JsonUtil.toList(StringUtil.toString(target)), name);
        }
        // 如果目标对象是CircularlyAccessibleValueObject（NC的VO）
        // if (target instanceof CircularlyAccessibleValueObject)
        // { return ((CircularlyAccessibleValueObject) target).getAttributeValue((String) name); }
        // 如果以上情况都未命中，则认为这个对象是VO
        if (name instanceof String)
        {
            String getName = NamingUtil.getNaming(name.toString());
            String getNameWithBoolean = NamingUtil.getNaming(name.toString(), true);
            
            if (ReflectionUtil.containsMethod(target, getName))
            {
                return ReflectionUtil.invoke(target, getName);
            }
            else if (ReflectionUtil.containsMethod(target, getNameWithBoolean))
            {
                return ReflectionUtil.invoke(target, getNameWithBoolean);
            }
            else
            {
                throw new RuntimeException(target.getClass().getName() + "不存在" + name + "属性对应的Getter");
            }
        }
        throw new RuntimeException("无法获取" + target.getClass().getName() + "对象的" + name + "字段");
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 往一个对象中设置值
     *
     * @param targetObj 目标对象
     * @param name 名称或数组下标
     * @param value 值 <br>
     * @void <br>
     * @methods pers.bc.utils.pub.PubEnvUtilbc#setObjValue <br>
     * @author licheng <br>
     * @date Created on 2019年3月24日 <br>
     * @time 下午7:58:17 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    @SuppressWarnings("unchecked")
    public static void setObjValue(Object targetObj, Object name, Object value)
    {
        // 如果是Map，用name作为key返回对应的value
        if ((targetObj instanceof Map) && (name instanceof String))
        {
            ((Map<Object, Object>) targetObj).put(name, value);
            return;
        }
        // 如果是List，用name作为索引，返回下标对应的对象
        if ((targetObj instanceof List) && (name instanceof Integer))
        {
            ((List<Object>) targetObj).set((Integer) name, value);
            return;
        }
        if ((targetObj instanceof List) && (name instanceof String))
        {
            throw new RuntimeException("List对象不可用String作为key进行写入");
        }
        // 如果目标对象是数组
        if (targetObj.getClass().isArray() && (name instanceof Integer))
        {
            Array.set(targetObj, (Integer) name, value);
            return;
        }
        if (targetObj.getClass().isArray() && (name instanceof String))
        {
            throw new RuntimeException("数组不可用String作为key进行写入");
        }
        
        throw new RuntimeException("无法写入" + targetObj.getClass().getName() + "对象的" + name + "字段");
    }

    public static void setValNotNON(Object targetObj, Object name, Object value)
    { if (PubEnvUtil.isNotEmptyObj(value))setObjValue(targetObj, name, value); }
    
    /**
     * *********************************************************** <br>
     * 说明：“==”比较两个变量本身的值，即两个对象在内存中的首地址<br>
     * 当这两个地址相等时，判断结果为true，否则结果为false<br>
     * 两对象为null返回false<br>
     * 两个变量的内存地址不一样，也就是说它们指向的对象不 一样，<br>
     *
     * @param obj1
     * @param obj2
     * @return <br>
     * @boolean <br>
     * @methods #BeEqualTo <br>
     * @author licheng <br>
     * @date Created on 2019年11月23日 <br>
     * @time 下午10:15:18 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static boolean equality(Object obj1, Object obj2)
    {
        if (isEmptyObj(obj1) || isEmptyObj(obj2))
        {
            return false;
        }
        
        return obj1 == obj2;
    }
    
    /**
     * *********************************************************** <br>
     * 说明： String 不区分大小写<br>
     *
     * @param obj1
     * @param obj2
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtilbc#equalsIgnoreCase <br>
     * @author LiBencheng <br>
     * @date Created on 2020-11-14 <br>
     * @time 下午5:14:31 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static boolean equalsIgnoreCase(String obj1, String obj2)
    {
        if (isEmptyObj(obj1) || isEmptyObj(obj2))
        {
            return false;
        }
        return equals(obj1.toLowerCase(), obj2.toLowerCase());
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 万能相等 equals，支持深度比较<br>
     * 判断某个特征值来判断两个对象是否“等价”，<br>
     * 当这两个对象等价时，判断结果为true，否则结果为false<br>
     * 两对象为null返回false<br>
     * <br>
     * 注意: (Object类中的equals方法是用来比较“地址”的，所以等于false;<br>
     * equals方法对于字符串来说是比较内容的，而对于非字符串来说是比较，其指向的对象是否相同的)<br>
     *
     * @param obj1
     * @param obj2
     * @return <br>
     * @boolean <br>
     * @methods #equals <br>
     * @author licheng <br>
     * @date Created on 2019年11月23日 <br>
     * @time 下午10:11:27 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static boolean equals(Object obj1, Object obj2)
    {
        try
        {
            boolean eq;
            if (obj1 == obj2)
            {
                eq = true;
            }
            else if (obj1 == null && obj2 != null)
            {
                eq = false;
            }
            else if (obj2 == null && obj1 != null)
            {
                eq = false;
            }
            else if ((obj1 instanceof Integer || obj2 instanceof Integer)
                && Integer.parseInt(obj1.toString()) == Integer.parseInt(obj2.toString()))
            {
                eq = true;
            }
            else if ((obj1 instanceof Double || obj2 instanceof Double)
                && Double.parseDouble(obj1.toString()) == Double.parseDouble(obj2.toString()))
            {
                eq = true;
            }
            else if ((obj1 instanceof Long || obj2 instanceof Long) && Long.parseLong(obj1.toString()) == Long.parseLong(obj2.toString()))
            {
                eq = true;
            }
            else if ((obj1 instanceof Short || obj2 instanceof Short)
                && Short.parseShort(obj1.toString()) == Short.parseShort(obj2.toString()))
            {
                eq = true;
            }
            else if ((obj1 instanceof Float || obj2 instanceof Float)
                && Float.parseFloat(obj1.toString()) == Float.parseFloat(obj2.toString()))
            {
                eq = true;
            }
            else if ((obj1 instanceof String || obj2 instanceof String) && obj1.toString().equals(obj2.toString()))
            {
                eq = true;
            }
            else if (obj1 instanceof Object[] && obj2 instanceof Object[])
            {
                eq = Arrays.deepEquals((Object[]) obj1, (Object[]) obj2);
            }
            else if (obj1 instanceof byte[] && obj2 instanceof byte[])
            {
                eq = Arrays.equals((byte[]) obj1, (byte[]) obj2);
            }
            else if (obj1 instanceof short[] && obj2 instanceof short[])
            {
                eq = Arrays.equals((short[]) obj1, (short[]) obj2);
            }
            else if (obj1 instanceof int[] && obj2 instanceof int[])
            {
                eq = Arrays.equals((int[]) obj1, (int[]) obj2);
            }
            else if (obj1 instanceof long[] && obj2 instanceof long[])
            {
                eq = Arrays.equals((long[]) obj1, (long[]) obj2);
            }
            else if (obj1 instanceof char[] && obj2 instanceof char[])
            {
                eq = Arrays.equals((char[]) obj1, (char[]) obj2);
            }
            else if (obj1 instanceof float[] && obj2 instanceof float[])
            {
                eq = Arrays.equals((float[]) obj1, (float[]) obj2);
            }
            else if (obj1 instanceof double[] && obj2 instanceof double[])
            {
                eq = Arrays.equals((double[]) obj1, (double[]) obj2);
            }
            else if (obj1 instanceof boolean[] && obj2 instanceof boolean[])
            {
                eq = Arrays.equals((boolean[]) obj1, (boolean[]) obj2);
            }
            else
            {
                eq = false;
            }
            
            return eq;
        }
        catch (Exception e)
        {
            return false;
        }
    }
    
    /*************************************************************
     * <br>
     *
     * 说明: equals 返回false <br>
     *
     * @Description <br>
     * @Date Created on 2022/3/2 19:36 <br>
     * @param obj1
     * @param obj2 <br>
     * @return boolean <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     *************************************************************          <br>
     */
    public static boolean unEquals(Object obj1, Object obj2)
    {
        return !equals(obj1, obj2);
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 包含某一个元素
     *
     * @param element
     * @param t
     * @param <T> <br>
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-8-2
     * @time 上午10:21:38
     * @version 1.0 <br>
     * @see
     */
    public static <T> boolean contains(Object element, T... t)
    {
        if (isNullObj(element)) return false;
        return Arrays.asList(t).contains(element);
    } 
    
    /**
     * *********************************************************** <br>
     * 说明： 包含某一个子元素,支持空包含空
     *
     * @param element
     * @param t
     * @param <T> <br>
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-8-2
     * @time 上午10:21:38
     * @version 1.0 <br>
     * @see
     */
    public static <T> boolean containStr(String element, T... t)
    {
        if (isNullObj(element)) return false;
        List<T> ls = Arrays.asList(t);
        for (int i = 0, j = PubEnvUtil.getSize(ls); i < j; i++)
        {
            if (element.contains(StringUtil.valueOfEmpty(ls.get(i))))
            { return true; }
        }
        
        return false;
    }
    
    /**
     * *********************************************************** <br>
     * *说明：  字符串必须包含所有的子元素（字符串），返回true <br>
     * @see <br>
     * @param <T>
     * @param element 
     * @param t 子元素
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#containAllStr <br>
     * @author LiBencheng <br>
     * @date Created on 2023年11月24日 <br>
     * @time 16:13:00 <br>
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static <T> boolean containAllStr(String element, T... t)
    {
        if (isNullObj(element)) return false;
        List<T> ls = Arrays.asList(t);
        for (int i = 0, j = PubEnvUtil.getSize(ls); i < j; i++)
        {
            if (!element.contains(StringUtil.valueOfEmpty(ls.get(i))))
            { return false;  }
        }
        
        return true;
    }

    /**
     * *********************************************************** <br>
     * *说明：包含某一个子元素，子元素去前后空格 <br>
     * @see <br>
     * @param element
     * @param t
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#containStr <br>
     * @author LiBencheng <br>
     * @date Created on 2024-6-20 <br>
     * @time 上午11:11:27 <br>
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static <T> boolean containStrTrim(String element, T... t)
    {
        if (isNullObj(element)) return false;
        List<T> ls = Arrays.asList(t);
        for (int i = 0, j = PubEnvUtil.getSize(ls); i < j; i++)
        {
            if (element.contains(StringUtil.valueOfEmpty(ls.get(i)).trim()))
            { return true; }
        }
        
        return false;
    }
    
    /**
     * *********************************************************** <br>
     * *说明： 字符串必须包含所有的子元素（字符串），返回true 支持空包含空<br>
     * @see <br>
     * @param element
     * @param t
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtil#containAllStrTrim <br>
     * @author LiBencheng <br>
     * @date Created on 2024-6-20 <br>
     * @time 上午11:38:27 <br>
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static <T> boolean containAllStrTrim(String element, T... t)
    {
        if (isNullObj(element)) return false;
        List<T> ls = Arrays.asList(t);
        for (int i = 0, j = PubEnvUtil.getSize(ls); i < j; i++)
        {
            if (!element.contains(StringUtil.valueOfEmpty(ls.get(i)).trim()))
            { return false;  }
        }
        
        return true;
    }
    
    /**
     * *********************************************************** <br>
     * 说明： java 类型判断方法<br>
     * 和instanceof一样的功能<br>
     *
     * @param zlass
     * @param object
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtilbc#isInstance <br>
     * @author LiBencheng <br>
     * @date Created on 2020-4-28 <br>
     * @time 下午11:23:56 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isInstance(Class<?> zlass, Object object)
    {
        return zlass.isInstance(object);
    }
    
    /**
     * *********************************************************** <br>
     * 说明：java 类型判断方法: 自身类.class.isAssignableFrom(自身类或子类.class)<br>
     * 和instanceof一样的功能 <br>
     *
     * @param C1
     * @param C2
     * @return <br>
     * @boolean <br>
     * @methods pers.bc.utils.pub.PubEnvUtilbc#isAssignableFrom <br>
     * @author LiBencheng <br>
     * @date Created on 2020-4-28 <br>
     * @time 下午11:24:54 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isAssignableFrom(Class<?> C1, Class<?> C2)
    {
        return C1.isAssignableFrom(C2);
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 检查是否是数字<br>
     *
     * @param value
     * @return <br>
     * @boolean <br>
     * @methods nc.puobj2.itf.tools.puobj2.PubOftenUtilbc#isNumber <br>
     * @author licheng <br>
     * @date Created on 2019-10-31 <br>
     * @time 下午3:30:47 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static boolean isNumber(String value)
    {
        String patternStr = "^\\d+$";
        Pattern p = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
        // 忽略大小写;
        Matcher m = p.matcher(value);
        return m.find();
    }
    
    /*************************************************************
     * <br>
     *
     * 说明:正数、负数、和小数 <br>
     *
     * @Description <br>
     * @Date Created on 2021/10/19 11:25 <br>
     * @Param [value] <br>
     * @return boolean <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     *************************************************************          <br>
     */
    public static boolean isCalcNumber(String value)
    {
        String patternStr = "^(\\-|\\+)?\\d+(\\.\\d+)?$";
        // 忽略大小写;
        Pattern p = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(value);
        return m.find();
    }
    
    /*************************************************************
     * <br>
     *
     * 说明: <br>
     *
     * @Description <br>
     * @Date Created on 2021/10/30 18:43 <br>
     * @Param [objValue] <br>
     * @return java.lang.Double <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     *************************************************************          <br>
     */
    public static Double parseDouble(Object objValue)
    {
        String str = StringUtil.valueOfZero(objValue).replace(PubEnvUtil.COMMA, PubEnvUtil.EMPTY);
        return isCalcNumber(str) ? ofNullValue(str) : Double.valueOf(PubEnvUtil.ZERO);
    }
    
//     public static String parseDob2Scale(Object objValue)
//     { return parseDobScale(objValue, 2); }
//    
//     public static String parseDobScale(Object objValue, int scale)
//     { return StringUtil.valueOfZero(NumberUtil.round(parseDouble(objValue), scale)); }
    
    /*************************************************************
     * <br>
     *
     * 说明: <br>
     *
     * @Description <br>
     * @Date Created on 2021/10/30 18:42 <br>
     * @Param [objValue] <br>
     * @return java.math.BigDecimal <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     *************************************************************          <br>
     */
    public static BigDecimal parseBigDecimal(Object objValue)
    {
        return BigDecimal.valueOf(parseDouble(objValue));
    }
    
    public static Double ofNullValue(String str)
    {
        return Double.valueOf(str).isNaN() ? 0D : Double.parseDouble(str);
    }
    
    /**
     * *********************************************************** <br>
     * 说明： 判断字符串是否是符合指定格式的时间
     *
     * @param date 时间字符串
     * @param format 时间格式
     * @return
     * @boolean
     * @author licheng
     * @date Created on 2019-7-24
     * @time 下午6:32:19
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see
     */
    public static boolean isDate(String date, String format)
    {
        try
        {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            sdf.parse(date);
            return true;
        }
        catch (ParseException e)
        {
            return false;
        }
        
    }
    
    /**
     * *********************************************************** <br>
     * 说明：获取一个double类型的数字的小数位有多长 <br>
     *
     * @param dd
     * @return <br>
     * @int <br>
     * @methods #doueleBitCount <br>
     * @author licheng <br>
     * @date Created on 2019年11月23日 <br>
     * @time 下午10:11:15 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static int doueleBitCount(double dd)
    {
        String temp = String.valueOf(dd);
        int i = temp.indexOf(".");
        if (i > -1)
        {
            return temp.length() - i - 1;
        }
        return 0;
        
    }
    
    /**
     * *********************************************************** <br>
     * 说明： <br>
     *
     * @param arr
     * @return <br>
     * @Integer[] <br>
     * @methods #doubleBitCount <br>
     * @author licheng <br>
     * @date Created on 2019年11月23日 <br>
     * @time 下午10:11:07 <br>
     * @version 1.0 <br>
     *          ************************************************************ <br>
     * @see <br>
     */
    public static Integer[] doubleBitCount(double[] arr)
    {
        Integer[] len = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++)
        {
            len[i] = doueleBitCount(arr[i]);
        }
        return len;
    }
    
}
